package com.itstyle.quartz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itstyle.quartz.domain.JobKettle;
import com.itstyle.quartz.domain.JobKettleLogs;
import com.itstyle.quartz.dynamicquery.DynamicQuery;
import com.itstyle.quartz.entity.*;
import com.itstyle.quartz.service.dao.IJobService;
import com.itstyle.quartz.service.mapper.JobMapper;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

@Service("jobService")
@Transactional
//@Repository
public class JobServiceImpl implements IJobService {
    private static final Logger logger = LoggerFactory.getLogger(JobServiceImpl.class);
	@Autowired
	private DynamicQuery dynamicQuery;
    @Autowired
    private Scheduler scheduler;
    @Autowired
    private JobMapper jobMapper;
    @Autowired
    private JdbcTemplate jdbcTemplate;

	@Override
	public Result listQuartzEntity(QuartzEntity quartz, Integer pageNo, Integer pageSize) throws SchedulerException {
	    String countSql = "SELECT COUNT(*) FROM QRTZ_JOB_KETTLE_DETAILS AS job ";
        if(!StringUtils.isEmpty(quartz.getJOBNAME())){
            countSql+=" WHERE job.JOB_NAME like '%"+quartz.getJOBNAME().toString()+"%'";
        }
        Long totalCount = jdbcTemplate.queryForObject(countSql, Long.class);
        PageBean<QuartzEntity> data = new PageBean<>();
        if(totalCount>0){
            StringBuffer nativeSql = new StringBuffer();
            nativeSql.append("SELECT job.JOB_NAME as jobName,job.JOB_GROUP as jobGroup,job.DESCRIPTION as description,job.JOB_CLASS_NAME as jobClassName,");
            nativeSql.append("cron.CRON_EXPRESSION as cronExpression,tri.TRIGGER_NAME as triggerName,decode(tri.TRIGGER_STATE,'WAITING','启动','PAUSED','暂停','ACQUIRED','启动','BLOCKED','阻塞','ERROR','错误','其他') as triggerState,");
            nativeSql.append("job.JOB_NAME as oldJobName,job.JOB_GROUP as oldJobGroup,kett.RUNTYPE AS runtype,kett.KETTLE_PATCH AS kettlepatch,decode(kett.KETTLE_DETAILS,'null','',kett.KETTLE_DETAILS) AS kettledetails ,kett.FILE_PATCH AS filepatch ");
            nativeSql.append("FROM qrtz_job_details AS job ");
            nativeSql.append("LEFT JOIN qrtz_triggers AS tri ON job.JOB_NAME = tri.JOB_NAME  AND job.JOB_GROUP = tri.JOB_GROUP ");
            nativeSql.append("LEFT JOIN qrtz_cron_triggers AS cron ON cron.TRIGGER_NAME = tri.TRIGGER_NAME AND cron.TRIGGER_GROUP= tri.JOB_GROUP LEFT JOIN QRTZ_JOB_KETTLE_DETAILS as kett on kett.JOB_NAME  = tri.JOB_NAME and kett.JOB_GROUP = tri.JOB_GROUP ");
            nativeSql.append("WHERE tri.TRIGGER_TYPE = 'CRON' and job.JOB_CLASS_NAME='"+quartz.getJOBCLASSNAME()+"'");
            Object[] params = new  Object[]{};
            if(!StringUtils.isEmpty(quartz.getJOBNAME())){
                nativeSql.append(" AND job.JOB_NAME like '%"+quartz.getJOBNAME().toString()+"%'");
                //params = new Object[]{quartz.getJOBNAME()};
            }
            Pageable pageable = PageRequest.of(pageNo-1,pageSize);
            List<QuartzEntity> list = dynamicQuery.nativeQueryPagingList(QuartzEntity.class,pageable, nativeSql.toString(), params);
            for (QuartzEntity quartzEntity : list) {
                JobKey key = new JobKey(quartzEntity.getJOBNAME(), quartzEntity.getJOBGROUP());
                JobDetail jobDetail = scheduler.getJobDetail(key);
                quartzEntity.setJOBMETHODNAME(jobDetail.getJobDataMap().getString("jobMethodName"));
            }
            data = new PageBean<>(list, totalCount);
        }
        return Result.ok(data);
	}

	@Override
	public Long listQuartzEntity(QuartzEntity quartz) {
		StringBuffer nativeSql = new StringBuffer();
		nativeSql.append("SELECT COUNT(*)");
		nativeSql.append("FROM qrtz_job_details AS job LEFT JOIN qrtz_triggers AS tri ON job.JOB_NAME = tri.JOB_NAME ");
		nativeSql.append("LEFT JOIN qrtz_cron_triggers AS cron ON cron.TRIGGER_NAME = tri.TRIGGER_NAME ");
		nativeSql.append("WHERE tri.TRIGGER_TYPE = 'CRON'");
		return jdbcTemplate.queryForObject(nativeSql.toString(),Long.class);
	}

    @Override
    @Transactional
    public void save(QuartzEntityVo quartzvo) throws Exception{

        //如果是修改  展示旧的 任务
        if(quartzvo.getOLDJOBGROUP()!=null && !"".equals(quartzvo.getOLDJOBGROUP())){
            JobKey key = new JobKey(quartzvo.getOLDJOBNAME(),quartzvo.getOLDJOBGROUP());
            //构建完job信息保存辅助信息入表
            Long totalCount = jobMapper.findKey(key.toString());
            if(totalCount>0){
               deleteJobKettle(key);
            }
            scheduler.deleteJob(key);
        }
        Class cls = Class.forName(quartzvo.getJOBCLASSNAME()) ;
        cls.newInstance();
        //构建job信息
        JobDetail job = JobBuilder.newJob(cls).withIdentity(quartzvo.getJOBNAME(),
                quartzvo.getJOBGROUP())
                .withDescription(quartzvo.getDESCRIPTION()).build();
        job.getJobDataMap().put("jobMethodName", quartzvo.getJOBMETHODNAME());
        JobKey job_key = job.getKey();
        List list = findOne(quartzvo);
        if (list.size()>0) {
            throw new Exception("任务名称或分组有重复");
        }
        //构建完job信息保存辅助信息入表
        saveJobKettle(quartzvo,job_key);

        // 触发时间点
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartzvo.getCRONEXPRESSION()).withMisfireHandlingInstructionDoNothing();
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger"+quartzvo.getJOBNAME(), quartzvo.getJOBGROUP())
                .startNow().withSchedule(cronScheduleBuilder).build();
        //交由Scheduler安排触发
        scheduler.scheduleJob(job, trigger);
    }

    @Override
    public int saveJobKettle(QuartzEntityVo quartzvo,JobKey key) {
        return  jobMapper.save(quartzvo.getJOBNAME(),quartzvo.getJOBGROUP(),quartzvo.getDESCRIPTION(),quartzvo.getRUNTYPE(),quartzvo.getKETTLEPATCH(),JSONObject.parseObject(quartzvo.getKETTLEDETAILS()),key.toString(),quartzvo.getFILEPATH());
    }

    @Override
    public int updateJobKettle(QuartzEntityVo quartzvo,JobKey key) {

        JobKettle jobKettle = new JobKettle();
        jobKettle.setJOB_NAME(quartzvo.getJOBNAME());
        jobKettle.setJOB_GROUP(quartzvo.getJOBGROUP());
        jobKettle.setDESCRIPTION(quartzvo.getDESCRIPTION());
        jobKettle.setRUNTYPE(quartzvo.getRUNTYPE());
        jobKettle.setKETTLE_DETAILS(quartzvo.getKETTLEDETAILS());

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("JOB_KEY",key);

        return jobMapper.update(jobKettle,queryWrapper);
    }

    @Override
    public List<QuartzEntityDt> listJobKettle(JobKey key) {
        List<QuartzEntityDt> list = jobMapper.list(key.toString());
        return list;
    }
    @Override
    public int deleteJobKettle(JobKey key) {
        String name = key.toString();
        return jobMapper.deleteJobKettle(name);
    }

    @Override
    public List<QuartzEntityBatchDt> listJobKettleBatch(JobKey key) {
        StringBuffer nativeSql = new StringBuffer();
        String name = key.getName();
        return jobMapper.batchList(name);
    }

    @Override
    public Result listJobKettleLogs(QuartzEntityLogsDt quartzEntityLogsDt,Integer pageNo, Integer pageSize) {
        String countSql = "SELECT COUNT(*) FROM QRTZ_JOB_KETTLE_LOGS AS job ";
        if(!StringUtils.isEmpty(quartzEntityLogsDt.getTHESELECTDATA())){
            countSql+="where to_date(job.BEGIN_TIME,'yyyy-MM-dd hh24:mi:ss') >=to_date('"+quartzEntityLogsDt.getTHESELECTDATA()+"','yyyy-MM-dd hh24:mi:ss') ";
        }else{
            countSql+="where to_date(job.BEGIN_TIME,'yyyy-MM-dd') =to_date(sysdate,'yyyy-MM-dd') ";
        }
        if(!StringUtils.isEmpty(quartzEntityLogsDt.getJOBKEY())){
            countSql+=" and job.JOB_KEY like '%"+quartzEntityLogsDt.getJOBKEY()+"%'";
        }
        Long totalCount = jdbcTemplate.queryForObject(countSql,Long.class);

        Pageable pageable = PageRequest.of(pageNo-1,pageSize);
        StringBuffer nativeSql = new StringBuffer();
        nativeSql.append("SELECT JOB_KEY AS JOBKEY,KETTLE_PATCH AS KETTLEPATCH,BEGIN_TIME AS BEGINTIME,END_TIME AS ENDTIME,STATUS,MESSAGE FROM QRTZ_JOB_KETTLE_LOGS ");
        if(!StringUtils.isEmpty(quartzEntityLogsDt.getTHESELECTDATA())){
            nativeSql.append(" where to_date(BEGIN_TIME,'yyyy-MM-dd hh24:mi:ss') >=to_date('").append(quartzEntityLogsDt.getTHESELECTDATA()).append("','yyyy-MM-dd hh24:mi:ss') ");
        }else{
            nativeSql.append(" where to_date(BEGIN_TIME,'yyyy-MM-dd') =to_date(sysdate,'yyyy-MM-dd') ");
        }
        if(!StringUtils.isEmpty(quartzEntityLogsDt.getJOBKEY())){
            nativeSql.append(" and JOB_KEY like '%"+quartzEntityLogsDt.getJOBKEY()+"%'");
        }
        nativeSql.append(" order by BEGIN_TIME DESC");
        Object[] params = new  Object[]{};
        List<QuartzEntityLogsDt> list = dynamicQuery.nativeQueryPagingList(QuartzEntityLogsDt.class,pageable, nativeSql.toString(), params);

        PageBean<QuartzEntityLogsDt> data = new PageBean<>(list, totalCount);
        return Result.ok(data);
    }

    @Override
    public int saveJobKettleLogs(QuartzEntityLogsDt quartzvo) {
        return jobMapper.saveLogs(quartzvo.getJOBKEY(),quartzvo.getKETTLEPATCH(),quartzvo.getBEGINTIME(),quartzvo.getENDTIME(),quartzvo.getSTATUS(),quartzvo.getMESSAGE(),quartzvo.getID());
    }

    @Override
    public int updateJobKettleLogs(QuartzEntityLogsDt quartzvo,JobKey key,String quartzid) {
        return jobMapper.updateMessage(quartzvo.getENDTIME(),quartzvo.getSTATUS(),quartzvo.getMESSAGE(),key.toString(),quartzid);
    }

    @Override
    public List<QuartzTaskCountDt> listJobSum() {
        return jobMapper.jobSum();
    }

    @Override
    public int saveYcData(String nativeSql) {
	    return jdbcTemplate.queryForObject(nativeSql,int.class);
    }

    @Override
    public int saveText(String str) {
        return jdbcTemplate.queryForObject(str,int.class);
    }

    @Override
    public List findOne(QuartzEntityVo quartzvo) {
        return jobMapper.findOne(quartzvo.getJOBNAME(),quartzvo.getJOBGROUP());
    }
}
